#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (c) 2011
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Author: Jesus Carrero <j.o.carrero@gmail.com>
# Mountain View, CA
#

"""
Use by Time steppers as base class.
"""

import logging


class DynamicSolverBase(object):

    """
    Base class for:
    1.- convection-reaccion diffusion
    2.- partial-integro differential equation.
    """

    __slots__ = [
        'm_dolog',
        'm_lbc',
        'm_load',
        'm_logger',
        'm_rbc',
        'm_tstepper',
        'm_ivalf',
        ]

    def __init__(self):
        """
      m_lbc ~ Boundary term, left hand side
      m_rbc ~ Boundary term, right hand side
      m_ivalf ~ initial condition (function)
    """

        (self.m_lbc, self.m_rbc) = (None, None)
        (self.m_load, self.m_dolog) = (None, None)
        (self.m_ivalf, self.m_tstepper) = (None, None)
        self.m_logger = logging.getLogger('self.m_logger')

    def _get_solver_hist(self):
        """ get solver history. """

        if self.m_tstepper.keep_history():
            return self.m_tstepper.get_history()
        else:
            raise Warning('Calling get hist when not hist was kept is illigal.')

    def do_log(self):
        """ log progresses. """

        return self.m_dolog

    def get_ivalf(self):
        """ initial value. """

        return self.m_ivalf

    def get_keep_hist(self):
        """ get flag keep history. """

        if self.m_tstepper is None:
            print 'set time stepper before getting the hist flag'
            assert False

        return self.m_tstepper.keep_history()

    def get_lbc(self):
        """ left boundary condition. this is a function (x, t). """

        return self.m_lbc

    def get_load(self):
        """ this terms shows up as mass forces. """

        return self.m_load

    def get_rbc(self):
        """ right boundary condition. this is a function (x, t). """

        return self.m_rbc

    def get_tstepper(self):
        """ return a pointer to the time stepper class. """

        if self.m_tstepper is None:
            self.log_error('Set a time stepper for the diffusion problem')
            self.log_error('use the API set_time_stepper( )')
            raise ValueError

        return self.m_tstepper

    def log_error(self, msgh):
        """ call this function from super classes to log messages. """

        self.m_logger.error(msgh)

    def log_info(self, msgh):
        """ call this function from super classes to log messages. """

        self.m_logger.info(msgh)

    def set_constraint(self, constraint):
        """ set linear complementary constraint."""

        self.m_tstepper.set_constraint(constraint)

    def set_dolog(self, dolog):
        """ log progress ??? """

        self.m_dolog = dolog

    def set_ivalf(self, ivalf):
        """ set solution at time 0. """

        self.m_ivalf = ivalf

    def set_lbc(self, left_bc):
        """ set left boundary condition. """

        self.m_lbc = left_bc

    def set_load(self, load):
        """ gravity terms. """

        self.m_load = load

    def set_rbc(self, right_bc):
        """ set right boundary condition. """

        self.m_rbc = right_bc

    def set_time_stepper(self, time_stepper):
        """ set time stepper."""

        self.m_tstepper = time_stepper

    def solve(self):
        """ solve pde """

        raise NotImplementedError, 'pure virtual method'


